/*
 * Copyright (c) 2019-2020, https://api.iot.10086.cn/(https://gitee.com/cmcc-iot-api/iot-card-open-application/).
 */
package cn.iot.card.open.sim.service;

import cn.iot.card.open.constants.Constants;
import cn.iot.card.open.constants.ErrorCode;
import cn.iot.card.open.constants.UrlConstants;
import cn.iot.card.open.ec.dto.ResponseDto;
import cn.iot.card.open.modular.model.ResultDTO;
import cn.iot.card.open.modular.token.TokenService;
import cn.iot.card.open.pojo.page.LayuiPageFactory;
import cn.iot.card.open.pojo.page.LayuiPageInfo;
import cn.iot.card.open.sim.dto.siminfo.*;
import cn.iot.card.open.sim.warpper.SimInfoForVoiceWrapper;
import cn.iot.card.open.util.ApiRequestUtil;
import cn.iot.card.open.util.CommonUtil;
import cn.iot.card.open.util.JsonUtil;
import cn.stylefeng.roses.core.reqres.response.ResponseData;
import cn.stylefeng.roses.kernel.model.exception.ServiceException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 物联卡综合信息---语音
 *
 * @author zhanlele
 * @date 20200315 19:33:09
 * @modify 20200315 zhanlele v1.1.2 创建
 * @since v1.1.2
 */
@Service
@Slf4j
public class SimInfoForVoiceService {

    @Autowired
    private TokenService tokenService;

    @Autowired
    private ApiRequestUtil apiRequestUtil;

    /**
     * 套餐内语音用量
     *
     * @param accountId 账户ID
     * @param transId   流水号
     * @param msisdn 物联卡号码
     * @param iccid 集成电路卡识别码
     * @param imsi 国际移动用户识别码
     * @return 返回 layui page info
     * @throws Exception
     * @author zhanlele
     * @date 20200315 19:21:16
     * @modify 20200315 zhanlele v1.1.2 创建
     * @since v1.1.2
     */
    public LayuiPageInfo packageVoiceUsed(String accountId, String transId, String msisdn,
                                          String iccid, String imsi) throws Exception {
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO resultDTO = doRequestPackageVoiceUsed(true, accountId, transId, msisdn, iccid, imsi);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!resultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(resultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = resultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token [accountId:{}] is invalid and start to get a new token.", transId, accountId);
            resultDTO = doRequestPackageVoiceUsed(false, accountId, transId, msisdn, iccid, imsi);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!resultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(resultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = resultDTO.getMsg();
        }

        ResponseDto<PackageGprsUsedDTO> responseDto = JsonUtil.parseJson(responseStr,
                new TypeReference<ResponseDto<PackageGprsUsedDTO>>(){});
        code = responseDto.getStatus();
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] query packageVoiceUsed error, error message is {}.", transId, responseDto.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }

        List<PackageGprsUsedDTO> resultList = responseDto.getResult();
        PackageGprsUsedDTO packageGprsUsedDTO = resultList.get(0);
        List<AccmMarginDTO> accmMarginDTOList = packageGprsUsedDTO.getAccmMarginList();
        Page<AccmMarginDTO> page = LayuiPageFactory.defaultPage();
        page.setRecords(accmMarginDTOList);
        page.setTotal(accmMarginDTOList.size());
        return LayuiPageFactory.createPageInfo(page);
    }

    /**
     * 调API，套餐内语音用量
     *
     * @param tokenValid token是否有效
     * @param accountId  账户ID
     * @param transId    流水号
     * @param msisdn 物联卡号码
     * @param iccid 集成电路卡识别码
     * @param imsi 国际移动用户识别码
     * @return 返回 result dto
     * @throws Exception
     * @author zhanlele
     * @date 20200315 18:13:52
     * @modify 20200315 zhanlele v1.1.2 创建
     * @since v1.1.2
     */
    private ResultDTO doRequestPackageVoiceUsed(boolean tokenValid, String accountId, String transId, String msisdn,
                                                String iccid, String imsi) throws Exception {
        ResultDTO tokenResultDTO = tokenService.getToken(tokenValid, accountId);
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            return tokenResultDTO;
        }

        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TOKEN, tokenResultDTO.getMsg());
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        if (StringUtils.isNotBlank(msisdn)) {
            parameterMap.put(Constants.REQUEST_PARAM_MSISDN, msisdn);
        }
        if (StringUtils.isNotBlank(iccid)) {
            parameterMap.put(Constants.REQUEST_PARAM_ICCID, iccid);
        }
        if (StringUtils.isNotBlank(imsi)) {
            parameterMap.put(Constants.REQUEST_PARAM_IMSI, imsi);
        }

        String methodUrl = apiRequestUtil.buildRequestUrl(parameterMap, UrlConstants.QUERY_PACKAGE_VOICE_USED);
        log.info("[{}] packageVoiceUsed request url is {}.", transId, methodUrl);

        tokenResultDTO.setMsg(apiRequestUtil.doGet(methodUrl));
        return tokenResultDTO;
    }

    /**
     * 个人智能网语音信息
     *
     * @param accountId 账户ID
     * @param transId   流水号
     * @param msisdn 物联卡号码
     * @param iccid 集成电路卡识别码
     * @param imsi 国际移动用户识别码
     * @return 返回 layui page info
     * @throws Exception
     * @author zhanlele
     * @date 20200315 21:04:23
     * @modify 20200315 zhanlele v1.1.2 创建
     * @since v1.1.2
     */
    public LayuiPageInfo smartVoiceInfo(String accountId, String transId, String msisdn,
                                        String iccid, String imsi) throws Exception {
        Page<PersonVoiceInfoDTO> page = LayuiPageFactory.defaultPage();
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO resultDTO = doRequestSmartVoiceInfo(true, accountId, transId, msisdn, iccid, imsi, page);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!resultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(resultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = resultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token [accountId:{}] is invalid and start to get a new token.", transId, accountId);
            resultDTO = doRequestSmartVoiceInfo(false, accountId, transId, msisdn, iccid, imsi, page);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!resultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(resultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = resultDTO.getMsg();
        }

        ResponseDto<PersonSmartVoiceDTO> responseDto = JsonUtil.parseJson(responseStr,
                new TypeReference<ResponseDto<PersonSmartVoiceDTO>>(){});
        code = responseDto.getStatus();
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] query smartVoiceInfo error, error message is {}.", transId, responseDto.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }

        List<PersonSmartVoiceDTO> resultList = responseDto.getResult();
        PersonSmartVoiceDTO personSmartVoiceDTO = resultList.get(0);
        List<PersonVoiceInfoDTO> perVoiceInfoList = personSmartVoiceDTO.getPerVoiceInfoList();

        page.setTotal(perVoiceInfoList.size());
        page.setRecords(perVoiceInfoList);
        String[] fieldNames = new String[]{Constants.CHANGE_DATE, Constants.CALLED_LOCK, Constants.WHITE_STATUS, Constants.LIMIT_SIGN};
        page = new SimInfoForVoiceWrapper<PersonVoiceInfoDTO>(page).wrap(fieldNames);
        return LayuiPageFactory.createPageInfo(page);
    }

    /**
     * 调API，个人智能网语音信息查询
     *
     * @param tokenValid token是否有效
     * @param accountId  账户ID
     * @param transId    流水号
     * @param msisdn 物联卡号码
     * @param iccid 集成电路卡识别码
     * @param imsi 国际移动用户识别码
     * @return 返回 result dto
     * @throws Exception
     * @author zhanlele
     * @date 20200315 20:11:02
     * @modify 20200315 zhanlele v1.1.2 创建
     * @since v1.1.2
     */
    private ResultDTO doRequestSmartVoiceInfo(boolean tokenValid, String accountId, String transId, String msisdn,
                                              String iccid, String imsi, Page page) throws Exception {
        ResultDTO tokenResultDTO = tokenService.getToken(tokenValid, accountId);
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            return tokenResultDTO;
        }

        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TOKEN, tokenResultDTO.getMsg());
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        parameterMap.put(Constants.REQUEST_PARAM_STARTNUM, String.valueOf(page.getCurrent()));
        parameterMap.put(Constants.REQUEST_PARAM_PAGESIZE, String.valueOf(page.getSize()));
        if (StringUtils.isNotBlank(msisdn)) {
            parameterMap.put(Constants.REQUEST_PARAM_MSISDN, msisdn);
        }
        if (StringUtils.isNotBlank(iccid)) {
            parameterMap.put(Constants.REQUEST_PARAM_ICCID, iccid);
        }
        if (StringUtils.isNotBlank(imsi)) {
            parameterMap.put(Constants.REQUEST_PARAM_IMSI, imsi);
        }

        String methodUrl = apiRequestUtil.buildRequestUrl(parameterMap, UrlConstants.QUERY_PERSON_SMART_VOICE);
        log.info("[{}] smartVoiceInfo request url is {}.", transId, methodUrl);

        tokenResultDTO.setMsg(apiRequestUtil.doGet(methodUrl));
        return tokenResultDTO;
    }

    /**
     * 群组成员语音白名单查询
     *
     * @param accountId 账户ID
     * @param transId   流水号
     * @param groupId   群组ID
     * @return 返回 layui page info
     * @author zhanlele
     * @date 20200315 22:48:40
     * @modify 20200315 zhanlele v1.1.2 创建
     * @since v1.1.2
     */
    public LayuiPageInfo groupVoiceWhite(String accountId, String transId, String groupId) throws Exception {
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO resultDTO = doRequestGroupVoiceWhite(true, accountId, transId, groupId);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!resultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(resultDTO.getCode());
            return LayuiPageFactory.cteateErrorMsg(errorCode);
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = resultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token [accountId:{}] is invalid and start to get a new token.", transId, accountId);
            resultDTO = doRequestGroupVoiceWhite(false, accountId, transId, groupId);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!resultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(resultDTO.getCode());
                return LayuiPageFactory.cteateErrorMsg(errorCode);
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = resultDTO.getMsg();
        }

        ResponseDto<GroupVoiceWhiteDTO> responseDto = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto<GroupVoiceWhiteDTO>>(){});
        code = responseDto.getStatus();
        if (!ErrorCode.SUCCESS.getCode().equals(code)) {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] query groupVoiceWhite error, error message is {}.", transId, responseDto.getMessage());
            return LayuiPageFactory.cteateErrorMsg(ErrorCode.getByCode(code));
        }

        List<GroupVoiceWhiteDTO> resultList = responseDto.getResult();
        GroupVoiceWhiteDTO groupVoiceWhiteDTO = resultList.get(0);
        List<VoiceWhiteDTO> voiceWhiteDTOList = groupVoiceWhiteDTO.getGroupVoiceWhiteList();
        Page<VoiceWhiteDTO> page = LayuiPageFactory.defaultPage();
        page.setTotal(voiceWhiteDTOList.size());
        page.setRecords(voiceWhiteDTOList);

        String[] fieldNames = new String[]{Constants.RESPONSE_STATUS};
        page = new SimInfoForVoiceWrapper<VoiceWhiteDTO>(page).wrap(fieldNames);
        return LayuiPageFactory.createPageInfo(page);
    }

    /**
     * 调API，群组语音白名单查询
     *
     * @param tokenValid token是否有效
     * @param accountId  账户ID
     * @param transId    流水号
     * @param groupId    群组ID
     * @return 返回 result dto
     * @throws Exception
     * @author zhanlele
     * @date 20200315 22:57:21
     * @modify 20200315 zhanlele v1.1.2 创建
     * @since v1.1.2
     */
    private ResultDTO doRequestGroupVoiceWhite(boolean tokenValid, String accountId,
                                               String transId, String groupId) throws Exception {
        ResultDTO tokenResultDTO = tokenService.getToken(tokenValid, accountId);
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            return tokenResultDTO;
        }

        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TOKEN, tokenResultDTO.getMsg());
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        parameterMap.put(Constants.REQUEST_GROUP_ID, groupId);

        String methodUrl = apiRequestUtil.buildRequestUrl(parameterMap, UrlConstants.QUERY_MEMBER_VOICE_WHITE);
        log.info("[{}] groupVoiceWhite request url is {}.", transId, methodUrl);

        tokenResultDTO.setMsg(apiRequestUtil.doGet(methodUrl));
        return tokenResultDTO;
    }

    /**
     * 群组成员语音白名单管理
     *
     * @param accountId                 账户ID
     * @param transId                   流水号
     * @param managerGroupVoiceWhiteDTO
     * @return 返回 response data
     * @throws Exception
     * @author zhanlele
     * @date 20200315 22:37:43
     * @modify 20200315 zhanlele v1.1.2 创建
     * @since v1.1.2
     */
    public ResponseData managerGroupVoiceWhite(String accountId, String transId, ManagerGroupVoiceWhiteDTO managerGroupVoiceWhiteDTO) throws Exception {
        // 调用api接口：先获取token，然后带着token调用api接口
        ResultDTO resultDTO = doRequestManagerGroupVoiceWhite(true, accountId, transId, managerGroupVoiceWhiteDTO);
        // 如果此处响应失败即为获取token失败，返回失败原因
        if (!resultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            ErrorCode errorCode = ErrorCode.getByCode(resultDTO.getCode());
            throw new ServiceException(Integer.valueOf(errorCode.getCode()), errorCode.getMsg());
        }
        // 获取token成功后解析api接口的响应结果
        String responseStr = resultDTO.getMsg();
        String code = CommonUtil.getApiRspCode(responseStr);
        // 获取api接口的响应结果状态码，如果状态码为12021（token不存在或已过期），则重新获取token后再次调用api接口
        if (ErrorCode.ERR12021.getCode().equals(code)) {
            log.warn("[{}] token [accountId:{}] is invalid and start to get a new token.", transId, accountId);
            resultDTO = doRequestManagerGroupVoiceWhite(false, accountId, transId, managerGroupVoiceWhiteDTO);
            // 如果此处响应失败即为获取token失败，返回失败原因
            if (!resultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
                ErrorCode errorCode = ErrorCode.getByCode(resultDTO.getCode());
                throw new ServiceException(Integer.valueOf(errorCode.getCode()), errorCode.getMsg());
            }
            // 获取token成功后，重置responseStr（api接口的响应结果）
            responseStr = resultDTO.getMsg();
        }

        ResponseDto responseDto = JsonUtil.parseJson(responseStr, new TypeReference<ResponseDto>(){});
        code = responseDto.getStatus();
        if (ErrorCode.SUCCESS.getCode().equals(code)) {
            return ResponseData.success();
        } else {
            // 如果api接口返回失败，则返回失败原因
            log.warn("[{}] managerGroupVoiceWhite error, error message is {}.", transId, responseDto.getMessage());
            ResponseData responseData = new ResponseData();
            responseData.setCode(Integer.valueOf(code));
            responseData.setMessage(responseDto.getMessage());
            return responseData;
        }
    }

    /**
     * 调API，成员语音白名单配置
     *
     * @param tokenValid                token是否有效
     * @param accountId                 账户ID
     * @param transId                   流水号
     * @param managerGroupVoiceWhiteDTO
     * @return 返回 result dto
     * @throws Exception
     * @author zhanlele
     * @date 20200315 22:28:21
     * @modify 20200315 zhanlele v1.1.2 创建
     * @since v1.1.2
     */
    private ResultDTO doRequestManagerGroupVoiceWhite(boolean tokenValid, String accountId, String transId,
                                                      ManagerGroupVoiceWhiteDTO managerGroupVoiceWhiteDTO) throws Exception {
        ResultDTO tokenResultDTO = tokenService.getToken(tokenValid, accountId);
        if (!tokenResultDTO.getCode().equals(ErrorCode.SUCCESS.getCode())) {
            return tokenResultDTO;
        }

        Map<String, String> parameterMap = new HashMap<>();
        parameterMap.put(Constants.REQUEST_PARAM_TOKEN, tokenResultDTO.getMsg());
        parameterMap.put(Constants.REQUEST_PARAM_TRANSID, transId);
        String cardType = managerGroupVoiceWhiteDTO.getCardType();
        String cardNum = managerGroupVoiceWhiteDTO.getCardNum();
        switch (cardType) {
            case Constants.REQUEST_PARAM_MSISDN:
                parameterMap.put(Constants.REQUEST_PARAM_MSISDN, cardNum);
                break;
            case Constants.REQUEST_PARAM_ICCID:
                parameterMap.put(Constants.REQUEST_PARAM_ICCID, cardNum);
                break;
            case Constants.REQUEST_PARAM_IMSI:
                parameterMap.put(Constants.REQUEST_PARAM_IMSI, cardNum);
                break;
        }
        parameterMap.put(Constants.REQUEST_GROUP_ID, managerGroupVoiceWhiteDTO.getGroupId());
        parameterMap.put(Constants.REQUEST_PARAM_OPERTYPE, managerGroupVoiceWhiteDTO.getOperType());
        parameterMap.put(Constants.REQUEST_PARAM_WHITENUMBER, managerGroupVoiceWhiteDTO.getWhiteNumber());

        String methodUrl = apiRequestUtil.buildRequestUrl(parameterMap, UrlConstants.CONFIG_MEMBER_VOICE_WHITE);
        log.info("[{}] managerGroupVoiceWhite request url is {}.", transId, methodUrl);

        tokenResultDTO.setMsg(apiRequestUtil.doGet(methodUrl));
        return tokenResultDTO;
    }
}
